package cn.tedu.mall.front.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontCategoryService;
import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import cn.tedu.mall.pojo.front.vo.FrontCategoryTreeVO;
import cn.tedu.mall.pojo.product.vo.CategoryStandardVO;
import cn.tedu.mall.product.service.front.IForFrontCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class FrontCategoryServiceImpl implements IFrontCategoryService {

    @DubboReference
    private IForFrontCategoryService dubboCategoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    public static final String CATEGORY_TREE_KEY="category_tree";

    @Override
    public FrontCategoryTreeVO categoryTree() {

        if(redisTemplate.hasKey(CATEGORY_TREE_KEY)){
            FrontCategoryTreeVO<FrontCategoryEntity> treeVO =
                    (FrontCategoryTreeVO<FrontCategoryEntity>) redisTemplate.boundValueOps(CATEGORY_TREE_KEY).get();
            return  treeVO;
        }

        List<CategoryStandardVO> standardVOS = dubboCategoryService.getCategoryList();
        //构建三级分类树。
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO =  initTree(standardVOS);
        //将三级分类树保存到Redis中，定义内容和有效期（测试：1min; 上线：24h）。
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY)
                .set(treeVO, 1, TimeUnit.MINUTES);
        return treeVO;
    }

    private FrontCategoryTreeVO<FrontCategoryEntity> initTree(List<CategoryStandardVO> standardVOS) {

        Map<Long ,List<FrontCategoryEntity>> map = new HashMap<>();
        log.info("开始构建三级分类树，节点【{}】", standardVOS.size());
        for(CategoryStandardVO categoryStandardVO : standardVOS){

            FrontCategoryEntity frontCategoryEntity = new FrontCategoryEntity();
            BeanUtils.copyProperties(categoryStandardVO, frontCategoryEntity);

            Long parentId = frontCategoryEntity.getParentId();
            if(!map.containsKey(parentId)){
                List<FrontCategoryEntity> value = new ArrayList<>();
                value.add(frontCategoryEntity);
                map.put(parentId, value);
            }else{
                map.get(parentId).add(frontCategoryEntity);
            }
        }
        //添加到children属性中
        //1.一级
        List<FrontCategoryEntity> firstLevels = map.get(0L);
        if(firstLevels==null || firstLevels.isEmpty()){
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR, "无一级分类对象");
        }
        for(FrontCategoryEntity firstLevel : firstLevels){
            //2.通过一级分类的ID寻找二级分类父ID
            Long secondLevelParentId = firstLevel.getId();
            List<FrontCategoryEntity> secondLevels = map.get(secondLevelParentId);
            if(secondLevels==null || secondLevels.isEmpty()){
                //日志报警告即可，跳过本次循环剩余内容
                log.warn("当前分类没有二级内容【{}】",secondLevelParentId);
                continue;
            }
            for(FrontCategoryEntity secondLevel : secondLevels){
                //3.通过二级分类ID获取三级分类父ID
                Long thirdLevelParentId = secondLevel.getId();
                List<FrontCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                if(thirdLevels==null||thirdLevels.isEmpty()){
                    log.warn("二级分类没有三级分类的内容【{}】", thirdLevelParentId);
                    continue;
                }
                secondLevel.setChildrens(thirdLevels);
            }
            firstLevel.setChildrens(secondLevels);
        }
        //确认完关系后，赋值
        FrontCategoryTreeVO<FrontCategoryEntity> frontCategoryTreeVO = new FrontCategoryTreeVO<>();
        frontCategoryTreeVO.setCategories(firstLevels);
        return frontCategoryTreeVO;
    }
}
